﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using Jacobi.Seesmic.FeedReader.Utilities;

namespace Jacobi.Seesmic.FeedReader.Model
{
    /// <summary>
    /// Manages a collection of <see cref="FeedInfo"/> items.
    /// </summary>
    /// <remarks>
    /// Must be public for xml serialization.
    /// </remarks>
    public sealed class FeedInfoCollection : ObservableCollection<FeedInfo>
    {
        private Dictionary<string, FeedInfo> _idMap = new Dictionary<string, FeedInfo>();

        /// <summary>
        /// Manages the internal Id-Map.
        /// </summary>
        protected override void ClearItems()
        {
            _idMap.Clear();
            base.ClearItems();
        }

        /// <summary>
        /// Manages the internal Id-Map.
        /// </summary>
        /// <param name="index">Zero-based index.</param>
        /// <param name="item">Must not be null.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods",
            MessageId = "1", Justification = "Guard")]
        protected override void InsertItem(int index, FeedInfo item)
        {
            item.ThrowIfArgumentIsNull("item");

            _idMap.Add(item.Url, item);

            base.InsertItem(index, item);
        }

        /// <summary>
        /// Manages the internal Id-Map.
        /// </summary>
        /// <param name="index">Zero-based index.</param>
        /// <param name="item">Must not be null.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods",
            MessageId = "1", Justification = "Guard")]
        protected override void SetItem(int index, FeedInfo item)
        {
            item.ThrowIfArgumentIsNull("item");

            _idMap.Add(item.Url, item);

            base.SetItem(index, item);
        }

        /// <summary>
        /// Manages the internal Id-Map.
        /// </summary>
        /// <param name="index">Zero-based index.</param>
        protected override void RemoveItem(int index)
        {
            var item = this[index];
            _idMap.Remove(item.Url);

            base.RemoveItem(index);
        }

        /// <summary>
        /// Adds a collection of <see cref="FeedInfo"/> items to this instance.
        /// </summary>
        /// <param name="collection">Must not be null.</param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods",
            MessageId = "0", Justification = "Guard")]
        public void AddRange(IEnumerable<FeedInfo> collection)
        {
            collection.ThrowIfArgumentIsNull("collection");

            foreach (var item in collection)
            {
                Add(item);
            }
        }

        /// <summary>
        /// Performs a deep copy of the collection.
        /// </summary>
        /// <returns>Never returns null.</returns>
        public FeedInfoCollection DeepCopy()
        {
            var collection = new FeedInfoCollection();

            foreach (var item in this)
            {
                collection.Add(new FeedInfo(item));
            }

            return collection;
        }

        /// <summary>
        /// Checks if the <paramref name="item"/> is present in the collection (by key).
        /// </summary>
        /// <param name="item">Must not be null.</param>
        /// <returns>Returns true if the <paramref name="item"/> is present.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods",
            MessageId = "0", Justification = "Guard")]
        public bool ContainsKey(FeedInfo item)
        {
            item.ThrowIfArgumentIsNull("item");

            return _idMap.ContainsKey(item.Url);
        }

        /// <summary>
        /// Gets the item that corresponds to the specified <paramref name="key"/>.
        /// </summary>
        /// <param name="key">Must not be null or empty.</param>
        /// <returns>Returns the item.</returns>
        public FeedInfo this[string key]
        {
            get { return _idMap[key]; }
        }
    }
}